<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Libs\Plugins\SendGrid;

use Srv\Libs\Common\CommNet;
use Srv\Libs\Common\CommJson;
use Srv\Libs\Common\CommValid;
use Srv\Libs\Frame\Logs;

class SendGridEmail
{
    private string $apiKey                  = '';       // apiKey
    private string $logPath                 = '';       // logPath
    private string $apiUrl                  = 'https://api.sendgrid.com/v3/mail/send';

    /**
     * @param string $apiKey
     * @param string $logPath
     * __construct
     */
    public function __construct(string $apiKey, string $logPath)
    {
        $this->apiKey       = $apiKey;
        $this->logPath      = $logPath;
    }

    /**
     * @param array $toList
     * @param string $from
     * @param string $fromName
     * @param string $subject
     * @param string $htmlBody
     * @return bool
     * 发送Html邮件
     */
    public function sendMailHtml(array $toList, string $from, string $fromName, string $subject, string $htmlBody):bool
    {
        if(count($toList) < 1 || !CommValid::isEmail($from) || strlen($subject) < 1 || strlen($htmlBody) < 1) return false;
        $toEmailList        = [];
        foreach($toList as $to){
            if(!is_string($to) || !CommValid::isEmail($to)) continue;
            $toEmailList[]  = ['email' => $to];
        }
        if(count($toEmailList) < 1) return false;
        $headerData         = [
            'Authorization'     => 'Bearer '.$this->apiKey,
            'Content-Type'      => 'application/json',
        ];
        $postData           = [
            'personalizations'  => [['to' => $toEmailList]],
            'from'              => ['email' => $from],
            'subject'           => $subject,
            'content'           => [['type' => 'text/html', 'value' => $htmlBody]],
        ];
        if(strlen($fromName) > 0) $postData['from']['name'] = $fromName;
        $postString         = count($postData) > 0 ?  CommJson::encodeArray($postData) : '';
        $param              = ['TIMEOUT' => 30, 'METHOD' => 'POST', 'POST_DATA' => $postString, 'HEADER' => $headerData];
        $resData            = CommNet::getUrlInfo($this->apiUrl, $param);   // docs: https://docs.sendgrid.com/api-reference/mail-send/mail-send
        $httpCode           = intval($resData['http_code']??0);
        $body               = $resData['body']??'';
        unset($postData['personalizations']['content']);
        if($httpCode >= 200 && $httpCode < 400 && !isset($body['errors'])){
            $this->writeLog(CommJson::encodeArray(['res' => 'OK', 'POST' => $postData['personalizations'], 'BODY' => $body]), __LINE__, __FILE__);
            return true;
        }
        $this->writeLog(CommJson::encodeArray(['res' => 'FAIL', 'POST' => $postData['personalizations'], 'BODY' => $body]), __LINE__, __FILE__);
        return false;
    }

    /**
     * @param array $toList
     * @param string $from
     * @param string $fromName
     * @param string $subject
     * @param string $content
     * @return bool
     * 发送文本邮件
     */
    public function sendMailText(array $toList, string $from, string $fromName, string $subject, string $content):bool
    {
        if(count($toList) < 1 || !CommValid::isEmail($from) || strlen($subject) < 1 || strlen($content) < 1) return false;
        $toEmailList        = [];
        foreach($toList as $to){
            if(!is_string($to) || !CommValid::isEmail($to)) continue;
            $toEmailList[]  = ['email' => $to];
        }
        if(count($toEmailList) < 1) return false;
        $headerData         = [
            'Authorization'     => 'Bearer '.$this->apiKey,
            'Content-Type'      => 'application/json',
        ];
        $postData           = [
            'personalizations'  => [['to' => $toEmailList]],
            'from'              => ['email' => $from],
            'subject'           => $subject,
            'content'           => [['type' => 'text/plain', 'value' => $content]],
        ];
        if(strlen($fromName) > 0) $postData['from']['name'] = $fromName;
        $postString         = count($postData) > 0 ?  CommJson::encodeArray($postData) : '';
        $param              = ['TIMEOUT' => 30, 'METHOD' => 'POST', 'POST_DATA' => $postString, 'HEADER' => $headerData];
        $resData            = CommNet::getUrlInfo($this->apiUrl, $param);   // docs: https://docs.sendgrid.com/api-reference/mail-send/mail-send
        $httpCode           = intval($resData['http_code']??0);
        $body               = $resData['body']??'';
        unset($postData['personalizations']['content']);
        if($httpCode >= 200 && $httpCode < 400 && !isset($body['errors'])){
            $this->writeLog(CommJson::encodeArray(['res' => 'OK', 'POST' => $postData['personalizations'], 'BODY' => $body]), __LINE__, __FILE__);
            return true;
        }
        $this->writeLog(CommJson::encodeArray(['res' => 'FAIL', 'POST' => $postData['personalizations'], 'BODY' => $body]), __LINE__, __FILE__);
        return false;
    }

    /**
     * @param string $logString
     * @param int $fileLine
     * @param string $filePath
     * @return void
     * writeLog
     */
    private function writeLog(string $logString, int $fileLine, string $filePath):void
    {
        if(strlen($this->logPath) > 0) Logs::info($logString, $fileLine, $filePath, $this->logPath);
    }
}